import os, pickle, wx
import tones
from wx.lib.expando import ExpandoTextCtrl
from gui import guiHelper, messageBox, settingsDialogs
from autoSettingsUtils.autoSettings import AutoSettings
import synthDriverHandler
# 语音规则配置信息
selfDir = os.path.dirname(__file__)
rulesFile = os.path.join(selfDir, 'rules.pkl')
def getRules():
    try:
        with open(rulesFile, 'rb') as f:
            return pickle.load(f)
    except (FileNotFoundError, EOFError):pass
    return {}
def setRules(rules):
    with open(rulesFile, 'wb') as f:
        pickle.dump(rules, f)
def getRuleConfig(name, key, defaultVal):
    rules = getRules()
    try:
        value = rules[name]
        if not value:
            return defaultVal
        return value[key]
    except:pass
    return defaultVal
def setRuleConfig(name, key, value):
    rules = getRules()
    if not name in rules.keys():
        rules[name] = {}
    rules[name][key] = value
    setRules(rules)
class VoiceSettingsPanel(settingsDialogs.AutoSettingsMixin, settingsDialogs.SettingsPanel):
    title = _("Voice")
    def getSettings(self) -> AutoSettings:
        return synthDriverHandler.getSynth()
    def makeSettings(self, settingsSizer):pass
    def getConfigSpec(self):
        spec = {}
        settings = self.getSettings()
        for setting in settings.supportedSettings:
            spec[setting.id] = setting._get_configSpec()
        spec['regex'] = "string(default='')"
        return spec
    def saveConfig(self, name, regex):
        settings = self.getSettings()
        for setting in settings.supportedSettings:
            value = getattr(settings, setting.id)
            if isinstance(setting.defaultVal, bool):
                value = bool(value)
            elif isinstance(setting.defaultVal, int):
                value = int(value)
            elif isinstance(setting.defaultVal, float):
                value =float(value)
            setRuleConfig(name, setting.id, value)
        setRuleConfig(name, 'regex', regex)
    def loadConfig(self, name):
        settings = self.getSettings()
        for setting in settings.supportedSettings:
            try:
                setattr(settings, setting.id, getRuleConfig(name, setting.id, setting.defaultVal))
            except:pass
        try:
            self.updateDriverSettings()
        except:pass
        return getRuleConfig(name, 'regex', '')
class SettingsDialog(settingsDialogs.SettingsDialog):
    title = _('NV 宝盒语音管理器')
    def makeSettings(self, settingsSizer):
        self.rules = getRules()
        self.rules_bak = self.rules.copy()
        self.ruleName = None
        bshSettings = guiHelper.BoxSizerHelper(self, sizer = settingsSizer)
        # 语音规则的组合框
        self.cRule = bshSettings.addLabeledControl(_('语音规则&R'), wx.Choice)
        self.cRule.Bind(wx.EVT_CHOICE, self.onRuleChanged)
        # 添加语音规则的按钮
        self.bNewRule = bshSettings.addItem(wx.Button(self, label = _("添加语音规则&N")))
        self.bNewRule.Bind(wx.EVT_BUTTON, self.onNewRule)
        # 删除语音规则的按钮
        self.bDeleteRule = bshSettings.addItem(wx.Button(self, label = _("删除语音规则&D")))
        self.bDeleteRule.Bind(wx.EVT_BUTTON, self.onDeleteRule)
        # 负责朗读什么文本的编辑框
        self.etcRegex = bshSettings.addLabeledControl(_("负责朗读&R"), ExpandoTextCtrl, style = wx.TE_READONLY)
        # 语音参数控制面板
        self.voiceSettingsPanel = VoiceSettingsPanel(self)
        bshSettings.addItem(self.voiceSettingsPanel)
    def postInit(self):
        self.updateRules()
    def updateRules(self, name = None, regex = None):
        index = self.cRule.GetSelection()
        self.cRule.Clear()
        for i, k in enumerate(self.rules.keys()):
            if name and name == k:
                index = i
            self.cRule.Append(k)
        self.cRule.SetFocus()
        if index < 0:
            index = 0
        elif index >= self.cRule.Count:
            index = self.cRule.Count -1
        self.cRule.SetSelection(index)
        if self.rules:
            self.etcRegex.Show()
            self.voiceSettingsPanel.Show()
        else:
            self.etcRegex.Hide()
            self.voiceSettingsPanel.Hide()
        self.onRuleChanged(None)
        if regex:
            self.etcRegex.SetValue(regex)
    def onRuleChanged(self, event):
        index = self.cRule.GetSelection()
        if index < 0:return
        name = self.cRule.Strings[index]
        if self.ruleName:
            self.voiceSettingsPanel.saveConfig(self.ruleName, self.etcRegex.GetValue())
        if name:
            self.etcRegex.SetValue(self.voiceSettingsPanel.loadConfig(name))
            self.ruleName = name
    def onNewRule(self, event):
        dialog = NewRuleDialog(self)
        btnId, name, regex = dialog.show()
        dialog.Destroy()
        if btnId != wx.ID_OK or not name or not regex:return
        self.rules[name] = self.voiceSettingsPanel.getConfigSpec()
        setRules(self.rules)
        self.updateRules(name, regex)
    def onDeleteRule(self, event):
        if wx.NO == messageBox(_('是否确定删除当前规则？'), _('注意：'), wx.YES | wx.NO, self):
            return
        name = self.cRule.Strings[self.cRule.GetSelection()]
        del self.rules[name]
        if self.ruleName == name:
            self.ruleName = None
        setRules(self.rules)
        self.updateRules()
    def onOk(self, event):
        # 保存配置数据
        if self.ruleName:
            self.voiceSettingsPanel.saveConfig(self.ruleName, self.etcRegex.GetValue())
        try:
            self.voiceSettingsPanel.onDiscard()
        except AttributeError:pass
        super().onOk(event)
    def onCancel(self, event):
        try:
            self.voiceSettingsPanel.onDiscard()
        except AttributeError:pass
        setRules(self.rules_bak)
        super().onCancel(event)
class NewRuleDialog(wx.Dialog):
    def __init__(self, parent = None):
        super().__init__(parent, wx.ID_ANY, title = _('创建语音规则'), style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER)
        self.stName = wx.StaticText(self, wx.ID_ANY, _('名称&N'))
        self.tcName = wx.TextCtrl(self, wx.ID_ANY)
        self.stRegex = wx.StaticText(self, wx.ID_ANY, _('正则&R'))
        self.tcRegex = wx.TextCtrl(self, wx.ID_ANY)
        self.buttons = self.CreateButtonSizer(wx.OK | wx.CANCEL)
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.stName, 0, wx.ALL, 5)
        self.sizer.Add(self.tcName, 1, wx.EXPAND | wx.ALL, 5)
        self.sizer.Add(self.stRegex, 0, wx.EXPAND | wx.ALL, 5)
        self.sizer.Add(self.tcRegex, 1, wx.EXPAND | wx.ALL, 5)
        self.sizer.Add(self.buttons, 0, wx.EXPAND | wx.ALL, 5)
        self.SetSizerAndFit(self.sizer)
        self.Center()
    def show(self):
        self.tcName.SetFocus()
        return self.ShowModal(), self.tcName.GetValue(), self.tcRegex.GetValue()
